package com.bdbit.ChargingStation.config;

import com.bdbit.ChargingStation.entity.ChargingPile;
import com.bdbit.ChargingStation.mapper.ChargingPileMapper;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.util.List;

@Slf4j
/**
 * MQTT客户端配置类，用于配置和创建MQTT连接相关的Bean。
 * 包含MQTT代理地址、客户端ID、用户名、密码等配置信息。
 * 提供了MQTT连接选项和MQTT客户端的Bean定义。
 */
@Configuration
public class MqttClientConfig {
    @Autowired
    private ChargingPileMapper chargingPileMapper;
    
    @Value("${mqtt.broker-url}")
    private String brokerUrl;

    @Value("${mqtt.client-id}")
    private String clientId;

    @Value("${mqtt.username}")
    private String username;

    @Value("${mqtt.password}")
    private String password;

    //@Value("${mqtt.topic}")
    //private String topic;

    private MqttClient mqttClient;

    // 关键修复：自动注入回调处理器
    @Autowired
    private MqttCallbackHandler mqttCallbackHandler;

    /**
     * 配置MQTT连接选项。
     * 设置清理会话、用户名、密码、连接超时时间、保持活动间隔和自动重连。
     *
     * @return 配置好的MQTT连接选项对象
     */
    @Bean
    public MqttConnectOptions mqttConnectOptions() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        options.setConnectionTimeout(10);
        options.setKeepAliveInterval(20);
        options.setAutomaticReconnect(true);
        return options;
    }

    /**
     * 创建并配置MQTT客户端实例。
     * 使用提供的连接选项连接到MQTT代理，并订阅指定主题。
     * 如果连接失败，将记录错误并抛出异常。
     *
     * @param options MQTT连接选项
     * @return 配置好的MQTT客户端实例
     * @throws MqttException 如果连接过程中发生异常
     */
    @Bean
    public MqttClient mqttClient(MqttConnectOptions options) throws MqttException {
        try {
            // 使用内存持久化
            mqttClient = new MqttClient(brokerUrl, clientId, new MemoryPersistence());

            // 修复：使用注入的回调处理器（不需要参数）
            mqttClient.setCallback(mqttCallbackHandler);

            log.info("正在连接到MQTT代理: {}", brokerUrl);
            mqttClient.connect(options);
            log.info("MQTT客户端连接成功");

            // 订阅主题

            List<ChargingPile> resultList = chargingPileMapper.selectAll();
            for(int i=0;i<resultList.size();i++) {
                String devicePublishTopic = resultList.get(i).getIccid();
                mqttClient.subscribe(devicePublishTopic, 2);
                log.info("已订阅主题: {}", devicePublishTopic);
            }
        } catch (MqttException e) {
            log.error("MQTT连接失败: {}", e.getMessage());
            throw e;
        }
        return mqttClient;
    }

    /**
     * 在Bean销毁前执行断开MQTT连接的操作
     * 此方法主要用于确保在应用关闭时，能够优雅地断开与MQTT服务器的连接，避免资源泄露
     */
    @PreDestroy
    public void disconnect() {
        // 检查mqttClient是否已初始化且当前处于连接状态
        if (mqttClient != null && mqttClient.isConnected()) {
            try {
                // 正常断开MQTT连接并关闭客户端
                mqttClient.disconnect();
                mqttClient.close();
                // 记录断开连接的日志信息
                log.info("MQTT客户端已安全断开连接");
            } catch (MqttException e) {
                // 如果断开连接过程中出现异常，则记录错误日志
                log.error("断开MQTT连接时出错", e);
            }
        }
    }

}